#include <qlib/db/dxf_rw.h>
#include <qlib/utils/gds_utils.h>
#include <spdlog/spdlog.h>
#include <sstream>
namespace qlib {

DxfRWInterface::DxfRWInterface(/* args */) {}

DxfRWInterface::~DxfRWInterface() {}

void DxfRWInterface::write_dxf(const std::string& filename, std::vector<std::shared_ptr<qlib::Cell>> cells,
                               const std::unordered_map<uint32_t, std::string>& layer_name,
                               std::map<uint32_t, std::vector<std::vector<std::pair<qlib::Vec2d, double>>>> post_sim_polygons) {
  resetWriter(filename);

  if (cells.size() > 0) {
    m_export_top_cell = cells[0];
  }

  // 提取所有需要写出的cell
  for (auto&& c : cells) {
    m_cells.insert(c);
    std::unordered_set<std::shared_ptr<qlib::Cell>> uniq_cells;
    c->recurse_find_cell(c, uniq_cells);

    for (auto&& depends : uniq_cells) {
      auto dep_cell = std::dynamic_pointer_cast<qlib::Cell>(depends);
      if (dep_cell)
        m_cells.insert(dep_cell);
    }
  }

  // layer names
  m_layer_name = layer_name;
  for (auto&& c : m_cells) {
    c->update_tags();
    std::vector<uint32_t> all_layers;
    std::set<qlib::Tag> library_set = c->tags;
    for (qlib::Tag i : library_set) {
      all_layers.push_back(i.layer);
    }

    for (auto&& l : all_layers) {
      // 如果用户没有传入图层编号对应的名字，默认使用“layer_编号”作为名字
      if (!m_layer_name.count(l)) {
        std::stringstream ss;
        ss << l;
        std::string str = "layer_" + ss.str();
        m_layer_name.insert({l, str});
      }
    }
  }

  // 后仿数据
  m_post_sim_polygons = post_sim_polygons;

  bool success = m_dxf_read_writer->write(this, DRW::Version::AC1027, false);
  return;  // data;
}

std::vector<std::shared_ptr<qlib::Cell>> DxfRWInterface::read_dxf(const std::string& fname, const std::string& top_cell_name,
                                                                  const double& scale_factor) {
  m_scale_factor = scale_factor;
  // write_file(data, fname);
  resetReader(fname, top_cell_name);
  bool success = m_dxf_read_writer->read(this, false);
  // 恢复引用指向
  for (auto i : cellToCells) {
    for (auto ref : i.second) {
      auto it = std::find_if(m_cells.begin(), m_cells.end(), [&ref](std::shared_ptr<qlib::Cell> cell) { return cell->name == ref->name; });
      if (it != m_cells.end()) {
        ref->cell = *it;
      }
    }
  }
  std::vector<std::shared_ptr<qlib::Cell>> temp;
  std::vector<std::shared_ptr<qlib::Cell>> _temp;
  temp.insert(temp.begin(), m_cells.begin(), m_cells.end());
  for (auto i : temp) {
    if (i->name == "*Model_Space" || i->name == "*Paper_Space")
      continue;
    if (i->name.rfind("*D", 0) == 0 && i->name.size() >= 2) {
      continue;
    }
    if (i->name.rfind("*Paper_Space", 0) == 0 && i->name.size() >= 12) {
      continue;
    }
    if (i->name.rfind("*MODEL_SPACE", 0) == 0 && i->name.size() >= 12) {
      continue;
    }
    if (i->name.rfind("*PAPER_SPACE", 0) == 0 && i->name.size() >= 12) {
      continue;
    }
    if (i->name.empty() == false && i->name[0] == '*') {  // 为了适配dxf中单元出现首字符为*的情况
      i->name.replace(0, 1, "_");
    }
    _temp.emplace_back(i);
  }
  return _temp;
}

std::unordered_map<std::string, uint32_t> DxfRWInterface::getNameLayer() {
  return m_name_layer;
}

// reader part, stores all in class dx_data
// header
void DxfRWInterface::addHeader(const DRW_Header* data) {}

// tables
void DxfRWInterface::addLType(const DRW_LType& data) {}
void DxfRWInterface::addLayer(const DRW_Layer& data) {
  // 读入图层名，默认编号按读入顺序自增
  m_name_layer.insert({data.name, m_layer++});
}
void DxfRWInterface::addDimStyle(const DRW_Dimstyle& data) {}
void DxfRWInterface::addVport(const DRW_Vport& data) {}
void DxfRWInterface::addTextStyle(const DRW_Textstyle& data) {}
void DxfRWInterface::addAppId(const DRW_AppId& data) {}

// blocks, match to cell in gds
void DxfRWInterface::addBlock(const DRW_Block& data) {
  // dxf文件中每个block对应gds中的cell
  m_curr_cell = std::make_shared<qlib::Cell>();
  m_curr_cell->name = data.name;
}
void DxfRWInterface::endBlock() {
  // block读入完毕，当前cell完成，进行下一个循环
  m_cells.insert(m_curr_cell);
  m_curr_cell = nullptr;
}

void DxfRWInterface::setBlock(const int /*handle*/) {}  // unused

// entities
// 处理几何实体
void DxfRWInterface::addPoint(const DRW_Point& data) {}
void DxfRWInterface::addLine(const DRW_Line& data) {
  // 线
  auto line = std::make_shared<qlib::Path>();
  line->spine.append(qlib::Vec2d(data.basePoint.x, data.basePoint.y));
  line->spine.append(qlib::Vec2d(data.secPoint.x, data.secPoint.y));
  line->width = 0.0;
  line->spine.tolerance = 1e-2;
  line->layer = m_name_layer.at(data.layer);
  line->datatype = 0;
  if (line->width == 0) {
    auto& ele = line->elements.emplace_back();
    auto& ho = ele.half_width_and_offset.emplace_back();
    ele.bend_type = qlib::BendType::Circular;
    ele.join_type = qlib::JoinType::Round;
  }

  line->transform(m_scale_factor, false, 0, {0, 0});
  for (int i = 0; i < line->spine.points.size(); i++) {
    line->spine.points[i] = qlib::gds_utils::roundFunc(line->spine.points[i], 1000);
  }
  // 判断几何实体属于哪个block，如果不属于任何block，写入到顶层cell
  if (m_curr_cell) {
    //entt::entity entity = m_curr_cell->reg.create();
    //m_curr_cell->reg.emplace<qlib::Path::s_ptr>(entity, line);
    m_curr_cell->spawn(line);
  } else {
    entt::entity entity = m_top_cell->reg.create();
    m_top_cell->spawn(line);
  }
}
void DxfRWInterface::addRay(const DRW_Ray& data) {}
void DxfRWInterface::addXline(const DRW_Xline& data) {}
void DxfRWInterface::addArc(const DRW_Arc& data) {
  // 弧线
  qlib::Vec2d start_pos{data.basePoint.x + data.radious * cos(data.staangle), data.basePoint.y + data.radious * sin(data.staangle)};

  auto line = std::make_shared<qlib::Path>();
  line->spine.append(start_pos);
  line->width = 0.0;
  line->spine.tolerance = 1e-2;
  line->layer = m_name_layer.at(data.layer);
  line->datatype = 0;
  if (line->width == 0) {
    auto& ele = line->elements.emplace_back();
    auto& ho = ele.half_width_and_offset.emplace_back();
    ele.bend_type = qlib::BendType::Circular;
    ele.join_type = qlib::JoinType::Round;
  }

  qlib::CurveInstruction items[6];
  if (data.staangle < data.endangle) {
    items[0].command = 'A';
    items[1].number = data.radious;
    items[2].number = data.staangle;
    items[3].number = data.endangle;
  } else {
    double start_angel, end_angle;
    start_angel = data.staangle - M_PIx2;
    end_angle = data.endangle;
    items[0].command = 'A';
    items[1].number = data.radious;
    items[2].number = start_angel;
    items[3].number = end_angle;
  }
  qlib::CurveInstruction* items_ptr = items;
  line->commands(items_ptr, 4);

  line->transform(m_scale_factor, false, 0, {0, 0});
  for (int i = 0; i < line->spine.points.size(); i++) {
    line->spine.points[i] = qlib::gds_utils::roundFunc(line->spine.points[i], 1000);
  }
  if (m_curr_cell) {
    // entt::entity entity = m_curr_cell->reg.create();
    // m_curr_cell->reg.emplace<qlib::Path::s_ptr>(entity, line);
    m_curr_cell->spawn(line);
  } else {
    m_top_cell->spawn(line);
    // m_top_cell->reg.emplace<qlib::Path::s_ptr>(entity, line);
  }
}
void DxfRWInterface::addCircle(const DRW_Circle& data) {
  // auto circle = std::make_shared<qlib::Circle>(qlib::Vec2d{data.basePoint.x, data.basePoint.y}, data.radious, 1e-3, m_name_layer.at(data.layer), 0);

  // circle->transform(m_scale_factor, false, {0, 0});
  // if (m_curr_cell) {
  //   // entt::entity entity = m_curr_cell->reg.create();
  //   // m_curr_cell->reg.emplace<qlib::Circle::s_ptr>(entity, circle);
  //   entt::entity entity = m_curr_cell->spawn(circle);

  //   for (auto [e, tag, circle] : m_curr_cell->reg.view<qlib::Tag, qlib::Circle::s_ptr>().each()) {
  //     int a = 0;
  //   }

  // } else {
  //   // entt::entity entity = m_top_cell->reg.create();
  //   // m_top_cell->reg.emplace<qlib::Circle::s_ptr>(entity, circle);
  //   entt::entity entity = m_top_cell->spawn(circle);

  //   for (auto [e, tag, circle] : m_top_cell->reg.view<qlib::Tag, qlib::Circle::s_ptr>().each()) {
  //     int a = 0;
  //   }
  // }

  // 长半轴半径以及旋转角度的
  auto radius_x = data.radious;
  auto radius_y = data.radious;
  auto center = qlib::Vec2d{data.basePoint.x, data.basePoint.y};
  auto circle = std::make_shared<qlib::Ellipse>();
  circle->center = center;
  circle->radius = qlib::Vec2d(radius_x, radius_y);

  circle->layer = m_name_layer.at(data.layer);

  circle->transform(m_scale_factor, false, {0, 0});
  if (m_curr_cell) {
    //entt::entity entity = m_curr_cell->reg.create();
    //m_curr_cell->reg.emplace<qlib::Ellipse::s_ptr>(entity, circle);
    m_curr_cell->spawn(circle);
  } else {
    //entt::entity entity = m_top_cell->reg.create();
    //m_top_cell->reg.emplace<qlib::Ellipse::s_ptr>(entity, circle);
    m_top_cell->spawn(circle);
  }
}
void DxfRWInterface::addEllipse(const DRW_Ellipse& data) {
  bool is_full_ellipse = data.staparam == 0.0 && ((data.endparam - 2 * M_PI) < 10e-5);
  if (is_full_ellipse == false) {
    // 椭圆弧
    DRW_Polyline pol_new;
    //auto tmp = data;
    //tmp.toPolyline(&pl);
    double ratio = data.ratio;
    double staparam = data.staparam;
    double endparam = data.endparam;
    int isccw = data.isccw;
    DRW_Coord secPoint = data.secPoint;
    int parts = 128;
    DRW_Coord basePoint = data.basePoint;

    double radMajor = sqrt(secPoint.x * secPoint.x + secPoint.y * secPoint.y);  // 长轴
    double radMinor = radMajor * ratio;                                         // 短轴
    double cosRot = cos(atan2(secPoint.y, secPoint.x));                         // 椭圆旋转角度的余弦值
    double sinRot = sin(atan2(secPoint.y, secPoint.x));                         // 椭圆旋转角度的正弦值
    double incAngle = (endparam - staparam) / parts;                            // 每个顶点的参数角度增量

    for (int i = 0; i <= parts; ++i) {
      double curAngle = staparam + i * incAngle;
      double cosCurr = cos(curAngle);
      double sinCurr = sin(curAngle);

      // 计算当前顶点的坐标
      double x = basePoint.x + (cosCurr * cosRot * radMajor) - (sinCurr * sinRot * radMinor);
      double y = basePoint.y + (cosCurr * sinRot * radMajor) + (sinCurr * cosRot * radMinor);

      // 添加顶点到多段线对象中
      pol_new.addVertex(DRW_Vertex(x, y, 0.0, 0.0));
    }

    // 设置多段线的属性
    if (fabs(endparam - staparam - M_PI * 2) < 1.0e-10) {
      pol_new.flags = 1;  // 如果是完整的椭圆弧，设置闭合标志
    }
    pol_new.layer = data.layer;
    pol_new.lineType = data.lineType;
    pol_new.color = data.color;
    pol_new.lWeight = data.lWeight;
    pol_new.extPoint = data.extPoint;

    addPolyline(pol_new);

    return;
  }
  // 长半轴半径以及旋转角度的
  auto angle = atan(data.secPoint.y / data.secPoint.x);
  auto radius_x = sqrt(pow(data.secPoint.x, 2) + pow(data.secPoint.y, 2));
  auto radius_y = radius_x * data.ratio;
  auto center = qlib::Vec2d{data.basePoint.x, data.basePoint.y};
  auto circle = std::make_shared<qlib::Ellipse>();
  circle->center = center;
  circle->radius = qlib::Vec2d(radius_x, radius_y);

  circle->layer = m_name_layer.at(data.layer);

  while (angle < 0) {
    angle += M_PIx2;
  }

  while (angle > M_PIx2) {
    angle -= M_PIx2;
  }
  circle->rotate(angle, center);

  circle->transform(m_scale_factor, false, {0, 0});
  //   for (int i = 0; i < circle->m_point_array.size(); i++) {
  //     circle->m_point_array[i] = gds_utils::roundFunc(circle->m_point_array[i], 1000);
  //   }
  // circle->m_angle = angle;
  if (m_curr_cell) {
    //entt::entity entity = m_curr_cell->reg.create();
    //m_curr_cell->reg.emplace<qlib::Ellipse::s_ptr>(entity, circle);
    m_curr_cell->spawn(circle);
  } else {
    //entt::entity entity = m_top_cell->reg.create();
    //m_top_cell->reg.emplace<qlib::Ellipse::s_ptr>(entity, circle);
    m_top_cell->spawn(circle);
  }
}

int ncircle_for_radius(double rad) {
  double accu = std::max(0.0, 0.001 / 1.0);

  //  This is roughly the limit where a circle will be 4 points always
  if (rad < accu * 3) {
    return 4;
  }

  //  num of points = 1 / delta
  double delta = acos(1.0 - accu / rad) / M_PI;

  return int(0.5 + std::max(4.0, 1.0 / std::max(1.0 / double(std::max(4, 100)), delta)));
}

void add_bulge_segment(std::vector<qlib::Vec2d>& points, qlib::Vec2d& p, double b) {
  if (!points.empty() && fabs(b) > 1e-10) {

    double a = 2.0 * atan(b);

    qlib::Vec2d p0 = points.back();
    qlib::Vec2d d = p - p0;
    qlib::Vec2d t = qlib::Vec2d(-d.y, d.x);
    qlib::Vec2d m = (p0 + d * 0.5) + t * (0.5 / tan(a));

    qlib::Vec2d r = p0 - m;
    qlib::Vec2d s(-r.y, r.x);

    int n = int(ceil(ncircle_for_radius(r.length()) * fabs(a) / M_PI));
    //int n = 40;
    double da = 2 * a / std::max(1, n);
    double dr = 1.0 / cos(0.5 * da);

    for (int i = 0; i < n; ++i) {
      points.push_back(m + r * (dr * cos(da * (0.5 + i))) + s * (dr * sin(da * (0.5 + i))));
    }
  }

  points.push_back(p);
}
void DxfRWInterface::addLWPolyline(const DRW_LWPolyline& data) {
  std::vector<qlib::Vec2d> points;
  bool is_last_point = false;
  int indexs = 0;
  bool isArc = false;
  double bulge = 0;
  for (auto&& i : data.vertlist) {
    {
      if (isArc == true) {
        if (points.empty()) {
          points.emplace_back(i->x, i->y);
          continue;
        }
        qlib::Vec2d tmp_p{i->x, i->y};
        add_bulge_segment(points, tmp_p, bulge);
        // auto arc_points = bulge2arc(points[points.size() - 1], Vec2(i->x, i->y), bulge);
        // for (auto&& p : arc_points) {
        //   points.emplace_back(p);
        // }
        isArc = false;
      }

      if (i->bulge > 0 || i->bulge < 0) {
        isArc = true;
        bulge = i->bulge;
      }
    }

    points.emplace_back(i->x, i->y);
    indexs++;
    // 最后一个点是圆弧，需要和起点生成圆弧
    if (indexs == data.vertlist.size() && data.flags == 1) {
      if (isArc == true) {
        qlib::Vec2d start_v = qlib::Vec2d(data.vertlist[0]->x, data.vertlist[0]->y);
        add_bulge_segment(points, start_v, bulge);
      }
    }
  }

  std::shared_ptr<qlib::Cell> cell;
  if (m_curr_cell) {
    cell = m_curr_cell;
  } else {
    cell = m_top_cell;
  }

  // dxf中的light wight polylin既可以是线段也可以是多边形，取决于flag
  if (data.flags) {
    auto polygon = std::make_shared<qlib::Polygon>();
    polygon->points = points;
    polygon->layer = m_name_layer.at(data.layer);

    polygon->transform(m_scale_factor, false, 0, {0, 0});
    for (int i = 0; i < polygon->points.size(); i++) {
      polygon->points[i] = qlib::gds_utils::roundFunc(polygon->points[i], 1000);
    }

    //entt::entity entity = cell->reg.create();
    //cell->reg.emplace<qlib::Polygon::s_ptr>(entity, polygon);
    cell->spawn(polygon);
  } else {
    auto p = std::make_shared<qlib::Path>();
    p->spine.points = points;
    p->spine.tolerance = 1e-2;
    p->width = data.width / 2;
    p->layer = m_name_layer.at(data.layer);
    p->datatype = 0;
    p->simple_path = data.flags ? true : false;

    if (p->width == 0) {
      auto& ele = p->elements.emplace_back();
      auto& ho = ele.half_width_and_offset.emplace_back();
      ele.bend_type = qlib::BendType::Circular;
      ele.join_type = qlib::JoinType::Round;
    }

    for (uint64_t i = 0; i < p->elements.size(); i++) {
      p->elements[i].half_width_and_offset.push_back(qlib::Vec2d{p->width, 0});
    }
    p->transform(m_scale_factor, false, 0, {0, 0});
    for (int i = 0; i < p->spine.points.size(); i++) {
      p->spine.points[i] = qlib::gds_utils::roundFunc(p->spine.points[i], 1000);
    }

    //entt::entity entity = cell->reg.create();
    //cell->reg.emplace<qlib::Path::s_ptr>(entity, p);
    cell->spawn(p);
  }
}

std::vector<qlib::Vec2d> bulge2arc(qlib::Vec2d point_start, qlib::Vec2d point_end, double bulge) {
  int num = 40 * abs(bulge);  // 计算圆弧离散多少个点
  std::vector<qlib::Vec2d> result;
  double c = (1 / bulge - bulge) / 2;
  qlib::Vec2d o = qlib::Vec2d((point_start.x + point_end.x - (point_end.y - point_start.y) * c) / 2,
                              (point_start.y + point_end.y + (point_end.x - point_start.x) * c) / 2);
  qlib::Vec2d _dis = point_start - o;
  double r = _dis.length();

  qlib::Vec2d dir_start = point_start - o;
  qlib::Vec2d dir_end = point_end - o;
  double angel_start = dir_start.angle();
  double angle_end = dir_end.angle();

  if (bulge > 0) {
    if (angle_end < angel_start) {
      if (angel_start < 0) {
        angel_start = angel_start + M_PI * 2;
      }
      if (angle_end < 0) {
        angle_end = angle_end + M_PI * 2;
      }
    }
  } else if (bulge < 0) {
    if (angle_end > angel_start) {
      if (angel_start > 0) {
        angel_start = angel_start - M_PI * 2;
      }
      if (angle_end > 0) {
        angle_end = angle_end - M_PI * 2;
      }
    }
  }

  double off_set = (angle_end - angel_start) / num;
  for (int i = 1; i < num - 1; i++) {
    double angle = angel_start + off_set * i;
    // 逆时针角度取圆弧点
    auto v = o + qlib::Vec2d{r * cos(angle), r * sin(angle)};
    result.push_back(v);
  }

  return result;
}
void DxfRWInterface::addPolyline(const DRW_Polyline& data) {
  // 为了适配klayout 存在"0"图层，却没有调用 addLayer(const DRW_Layer& data) override; 的问题
  if (data.layer == "0") {
    if (m_name_layer.find(data.layer) == m_name_layer.end()) {

      m_name_layer.insert({data.layer, m_layer++});
    }
  }
  std::vector<qlib::Vec2d> points;
  int indexs = 0;
  bool isArc = false;
  double bulge = 0;
  for (auto&& i : data.vertlist) {
    {
      if (isArc == true) {
        if (points.empty()) {
          points.emplace_back(i->basePoint.x, i->basePoint.y);
          continue;
        }
        qlib::Vec2d temp_p(i->basePoint.x, i->basePoint.y);
        add_bulge_segment(points, temp_p, bulge);
        isArc = false;
      }

      if (i->bulge > 0 || i->bulge < 0) {
        isArc = true;
        bulge = i->bulge;
      }
      points.emplace_back(i->basePoint.x, i->basePoint.y);
      indexs++;
      // 最后一个点是圆弧，需要和起点生成圆弧
      if (indexs == data.vertlist.size() && data.flags == 1) {
        if (isArc == true) {
          qlib::Vec2d start_v = qlib::Vec2d(data.vertlist[0]->basePoint.x, data.vertlist[0]->basePoint.y);
          add_bulge_segment(points, start_v, bulge);
        }
      }
    }

    //test 2024-10-24 huangyi
    qlib::Vec2d cur_point(i->basePoint.x, i->basePoint.y);
    if (points.size() > 0) {
      double cur_point_x_tran = std::round(cur_point.x * 1000) / 1000;
      double cur_point_y_tran = std::round(cur_point.y * 1000) / 1000;
      double back_point_x_tran = std::round(points.back().x * 1000) / 1000;
      double back_point_y_tran = std::round(points.back().y * 1000) / 1000;

      if (cur_point_x_tran == back_point_x_tran && cur_point_y_tran == back_point_y_tran) {
        continue;
      }
    }

    points.emplace_back(i->basePoint.x, i->basePoint.y);
  }
  std::shared_ptr<qlib::Cell> cell;
  if (m_curr_cell) {
    cell = m_curr_cell;
  } else {
    cell = m_top_cell;
  }

  for (int i = 0; i < points.size(); i++) {
    points[i] = qlib::gds_utils::roundFunc(points[i], 1000);
  }

  // dxf中的light wight polylin既可以是线段也可以是多边形，取决于flag
  if (data.flags) {
    auto polygon = std::make_shared<qlib::Polygon>();
    polygon->points = points;
    polygon->layer = m_name_layer.at(data.layer);

    polygon->transform(m_scale_factor, false, 0, {0, 0});
    for (int i = 0; i < polygon->points.size(); i++) {
      polygon->points[i] = qlib::gds_utils::roundFunc(polygon->points[i], 1000);
    }

    //entt::entity entity = cell->reg.create();
    //cell->reg.emplace<qlib::Polygon::s_ptr>(entity, polygon);
    cell->spawn(polygon);
  } else {
    auto p = std::make_shared<qlib::Path>();
    p->spine.points = points;
    p->spine.tolerance = 1e-2;
    p->width = data.defendwidth / 2;
    p->layer = m_name_layer.at(data.layer);
    p->datatype = 0;
    p->simple_path = data.flags ? true : false;
    for (uint64_t i = 0; i < p->elements.size(); i++) {
      p->elements[i].half_width_and_offset.push_back(qlib::Vec2d{p->width, 0});
    }

    p->transform(m_scale_factor, false, 0, {0, 0});
    for (int i = 0; i < p->spine.points.size(); i++) {
      p->spine.points[i] = qlib::gds_utils::roundFunc(p->spine.points[i], 1000);
    }

    //entt::entity entity = cell->reg.create();
    //cell->reg.emplace<qlib::Path::s_ptr>(entity, p);
    cell->spawn(p);
  }
}
void DxfRWInterface::addSpline(const DRW_Spline* data) {
  int a = 0;
}
void DxfRWInterface::addKnot(const DRW_Entity& data) {
  int a = 0;
}

void DxfRWInterface::addInsert(const DRW_Insert& data) {
  // dxf中的insert对应gds中的reference，但dxf中insert的阵列不能与reference的阵列完全对应
  // 因而不处理阵列
  auto cell_name = data.name;
  /*auto it = std::find_if(m_cells.begin(), m_cells.end(),
                           [&cell_name](std::shared_ptr<Cell> cell) {
                             return cell->m_name == cell_name;
                           });
    if (it != m_cells.end())*/
  {
    auto ref = std::make_shared<qlib::Reference>();
    // ref->ref_to(*it);
    ref->name = cell_name;
    ref->magnification = abs(data.xscale);
    ref->origin = qlib::Vec2d{data.basePoint.x, data.basePoint.y};
    ref->rotation = data.angle;

    if (cell_name == "7.20GHz_3243.45um") {
      int a = 0;
    }

    if (cell_name == "7.10GHz_3300.79um") {
      int a = 0;
    }

    if (cell_name == "res-airbridge") {
      int a = 0;
    }

    // 如果scale为负数，reference进行了翻转，角度减去pi(注：此规律是试出来的)   CJ 20230804
    if (data.xscale < 0) {
      ref->x_reflection = true;
      ref->rotation = data.angle - M_PI;
    }

    if (data.yscale < 0) {
      ref->x_reflection = true;
      // ref->rotation = data.angle + M_PI;
    }

    double ca = cos(0);
    double sa = sin(0);
    qlib::Vec2d q = ref->origin * m_scale_factor;
    // if (ref->x_reflection)
    //   q.y = -q.y;
    ref->origin.x = q.x * ca - q.y * sa + 0;
    ref->origin.y = q.x * sa + q.y * ca + 0;
    ref->origin = qlib::gds_utils::roundFunc(ref->origin, 1000);

    auto addRef = [&](std::shared_ptr<qlib::Cell> useCell) {
      //entt::entity entity = useCell->reg.create();
      //useCell->reg.emplace<qlib::Reference::s_ptr>(entity, ref);

      useCell->spawn(ref);

      auto temp = cellToCells.find(useCell);
      if (temp != cellToCells.end())
        temp->second.push_back(ref);
      else {
        std::vector<std::shared_ptr<qlib::Reference>> refs;
        refs.push_back(ref);
        cellToCells.insert({useCell, refs});
      }
    };
    if (m_curr_cell) {
      addRef(m_curr_cell);
    } else {
      addRef(m_top_cell);
    }
  }
}
void DxfRWInterface::addTrace(const DRW_Trace& data) {}
void DxfRWInterface::add3dFace(const DRW_3Dface& data) {}
void DxfRWInterface::addSolid(const DRW_Solid& data) {
  // dxf solid是矩形，有四个点，如下
  auto p = std::make_shared<qlib::Polygon>();
  p->points = std::vector<qlib::Vec2d>{qlib::Vec2d{data.basePoint.x, data.basePoint.y}, qlib::Vec2d{data.secPoint.x, data.secPoint.y},
                                       qlib::Vec2d{data.thirdPoint.x, data.thirdPoint.y}, qlib::Vec2d{data.fourPoint.x, data.fourPoint.y}};
  p->layer = m_name_layer.at(data.layer);
  p->transform(m_scale_factor, false, 0, {0, 0});
  for (int i = 0; i < p->points.size(); i++) {
    p->points[i] = qlib::gds_utils::roundFunc(p->points[i], 1000);
  }
  if (m_curr_cell) {
    // entt::entity entity = m_curr_cell->reg.create();
    // m_curr_cell->reg.emplace<qlib::Polygon::s_ptr>(entity, p);

    m_curr_cell->spawn(p);
  } else {
    // entt::entity entity = m_top_cell->reg.create();
    // m_top_cell->reg.emplace<qlib::Polygon::s_ptr>(entity, p);
    m_top_cell->spawn(p);
  }
}
void DxfRWInterface::addMText(const DRW_MText& data) {
#if 0
  auto text = GdsText::text_to_polygon(
      data.text, data.interlin, Vec2{data.basePoint.x, data.basePoint.y},
      bool(data.angle), m_name_layer.at(data.layer), 0);
  std::shared_ptr<Cell> cell;
  if (m_curr_cell) {
    cell = m_curr_cell;
  } else {
    cell = m_top_cell;
  }

  for (auto&& i : text) {
    i->transform(m_scale_factor, false, 0, {0, 0});
    cell->add_polygon(i);
  }
#endif
}
void DxfRWInterface::addText(const DRW_Text& data) {}
void DxfRWInterface::addDimAlign(const DRW_DimAligned* data) {}
void DxfRWInterface::addDimLinear(const DRW_DimLinear* data) {}
void DxfRWInterface::addDimRadial(const DRW_DimRadial* data) {}
void DxfRWInterface::addDimDiametric(const DRW_DimDiametric* data) {}
void DxfRWInterface::addDimAngular(const DRW_DimAngular* data) {}
void DxfRWInterface::addDimAngular3P(const DRW_DimAngular3p* data) {}
void DxfRWInterface::addDimOrdinate(const DRW_DimOrdinate* data) {}
void DxfRWInterface::addLeader(const DRW_Leader* data) {}
void DxfRWInterface::addHatch(const DRW_Hatch* data) {}
void DxfRWInterface::addViewport(const DRW_Viewport& data) {}
void DxfRWInterface::addImage(const DRW_Image* data) {}

void DxfRWInterface::linkImage(const DRW_ImageDef* data) {}

// writer part, send all in class dx_data to writer
void DxfRWInterface::addComment(const char* /*comment*/) {}

void DxfRWInterface::writeHeader(DRW_Header& data) {}

// blocks, match to cell in gds, block contains geometry entity belongs to this
// block
void DxfRWInterface::writeBlocks() {
  for (auto&& c : m_cells) {
    DRW_Block block;
    block.name = c->name;
    m_dxf_read_writer->writeBlock(&block);

    auto refs = c->reg.view<qlib::Reference::s_ptr>();

    for (auto [e, ref] : refs.each()) {
      if (nullptr == ref) {
        continue;
      }
      qlib::ReferencePtrArray refs;
      ref->apply_repetition(refs);
      refs.push_back(ref);
      for (auto&& r : refs) {
        auto refed_cell = r->cell;
        if (refed_cell) {
          DRW_Insert insert;
          insert.name = refed_cell->name;
          insert.basePoint.x = r->origin.x;
          insert.basePoint.y = r->origin.y;
          insert.xscale = r->magnification;
          insert.yscale = r->magnification;
          // gds is in revers angle
          insert.angle = r->rotation;
          if (r->x_reflection) {  // 参考导入dxf进行适配
            insert.xscale *= -1;
            insert.angle = r->rotation + M_PI;
          }
          m_dxf_read_writer->writeInsert(&insert);
        }
      }
    }

    // write geometry
    // collect polygons
    std::unordered_set<std::shared_ptr<qlib::Polygon>> polygons;
    std::unordered_set<std::shared_ptr<qlib::Ellipse>> ellipses;
    std::unordered_set<std::shared_ptr<qlib::Path>> lines;

    for (auto [e, poly] : c->reg.view<qlib::Polygon::s_ptr>().each()) {
      polygons.insert((poly));
    }

    for (auto [e, elli] : c->reg.view<qlib::Ellipse::s_ptr>().each()) {
      ellipses.insert((elli));
    }

    for (auto [e, rec] : c->reg.view<qlib::Rectangle::s_ptr>().each()) {
      polygons.insert(rec->to_polygon());
    }

    for (auto [e, fan] : c->reg.view<qlib::Fan::s_ptr>().each()) {
      polygons.insert((fan->to_polygon()));
    }

    for (auto [e, line] : c->reg.view<qlib::Path::s_ptr>().each()) {

      // 无宽度的线使用flexpath->to_gds导出  CJ 20230721
      if (line->width == 0) {
        lines.insert(line);
      } else {
        qlib::PolygonPtrArray pols;
        line->to_polygons(false, qlib::Tag{0, 0}, pols);
        for (auto&& p : pols) {
          polygons.insert(p);
        }
      }
    }

    for (auto [e, text] : c->reg.view<qlib::Text::s_ptr>().each()) {
      std::vector<qlib::Polygon::s_ptr> pols = text->to_polygons();
      for (const auto& p : pols) {
        polygons.insert(p);
      }
    }
    if (m_post_sim_polygons.size() == 0) {
      // polygons
      for (auto&& poly : polygons) {
        qlib::PolygonPtrArray polys;
        poly->apply_repetition(polys);
        polys.push_back(poly);
        for (auto&& p : polys) {
          DRW_LWPolyline line;
          line.layer = m_layer_name.at(p->layer);
          for (auto&& pos : p->points) {
            if (std::isnan(pos.x) || std::isnan(pos.y)) {
              // 删除异常值 HY 2024 0723
              continue;
            }
            line.addVertex(DRW_Vertex2D(pos.x, pos.y, 0));
          }
          // flags == 1 means close
          line.flags = 1;
          m_dxf_read_writer->writeLWPolyline(&line);
        }
      }
    }

    // 圆弧测试代码
    // DRW_LWPolyline test_arc;
    // test_arc.layer = "arc_layer";
    // double bulge = tan(M_PI / 4);
    // test_arc.addVertex(DRW_Vertex2D(0, 0, bulge));
    // test_arc.addVertex(DRW_Vertex2D(1000, 1000, 0));
    // // flags == 0 means not close line
    // test_arc.flags = 0;
    // m_dxf_read_writer->writeLWPolyline(&test_arc);

    // lines
    for (auto&& l : lines) {
      // 过滤掉只有一个点的线，HY 20240729
      if (l->spine.points.size() < 2) {
        continue;
      }

      DRW_LWPolyline line;
      line.layer = m_layer_name.at(l->layer);
      for (auto&& pos : l->spine.points) {
        auto line_pos = pos;
        line_pos.x = pos.x;
        line_pos.y = pos.y;
        line.addVertex(DRW_Vertex2D(line_pos.x, line_pos.y, 0));
      }
      // flags == 0 means not close line
      line.flags = 0;
      m_dxf_read_writer->writeLWPolyline(&line);
    }

    // ellipse
    // dxf中的椭圆信息表示不是很直观
    if (m_post_sim_polygons.size() == 0) {
      for (auto&& eli : ellipses) {
        // qlib::Polygon::s_ptr poly = eli->to_polygon();
        // qlib::PolygonPtrArray polys;
        // poly->apply_repetition(polys);
        // polys.push_back(poly);
        // for (auto&& p : polys) {
        DRW_Ellipse line;
        // line.layer = m_layer_name.at(p->layer);
        line.layer = m_layer_name.at(eli->layer);
        //auto center = p->get_center_pos();
        auto center = eli->center;
        // auto box = p->bounding_box();
        line.basePoint.x = center.x;
        line.basePoint.y = center.y;
        // 椭圆起始角度和结束角度
        line.staparam = 0;
        line.endparam = M_PIx2;
        // secPoint表示长半轴最远点坐标
        line.secPoint.x = eli->radius.x * cos(eli->rotation);
        line.secPoint.y = eli->radius.x * sin(eli->rotation);
        // 长短半轴比率
        line.ratio = eli->radius.y / eli->radius.x;
        // flags == 1 means close
        m_dxf_read_writer->writeEllipse(&line);
        // }
      }
    }
    for (auto [e, label] : c->reg.view<qlib::Label::s_ptr>().each()) {
      DRW_Text text;
      text.basePoint.x = label->origin.x;
      text.basePoint.y = label->origin.y;
      text.height = label->fontSize;
      text.angle = label->rotation;
      m_dxf_read_writer->writeText(&text);
    }
  }
  // 后仿数据写入
  for (const auto& pair : m_post_sim_polygons) {
    uint32_t layer = pair.first;
    const std::vector<std::vector<std::pair<qlib::Vec2d, double>>>& layer_polygons = pair.second;
    for (const std::vector<std::pair<qlib::Vec2d, double>>& poly : layer_polygons) {
      DRW_LWPolyline pol_line;
      pol_line.layer = m_layer_name.at(layer);
      for (const std::pair<qlib::Vec2d, double>& point_pair : poly) {
        qlib::Vec2d point = point_pair.first;
        double bulge = point_pair.second;
        pol_line.addVertex(DRW_Vertex2D(point.x, point.y, bulge));
      }
      pol_line.flags = 1;
      m_dxf_read_writer->writeLWPolyline(&pol_line);
    }
  }
}

//+ only send the name, needed by the reader to prepare handles of blocks &
// blockRecords
void DxfRWInterface::writeBlockRecords() {
  for (auto&& c : m_cells) {
    m_dxf_read_writer->writeBlockRecord(c->name);
  }
}
// write entities of model space and first paper_space
// top geometry
void DxfRWInterface::writeEntities() {
  if (m_export_top_cell) {
    DRW_Insert insert;
    insert.name = m_export_top_cell->name;
    m_dxf_read_writer->writeInsert(&insert);
  }
}
void DxfRWInterface::writeLTypes() {}
void DxfRWInterface::writeLayers() {
  for (auto&& l : m_layer_name) {
    DRW_Layer layer;
    layer.color = l.first % 250;  //颜色最大值为249
    layer.name = l.second;
    m_dxf_read_writer->writeLayer(&layer);
  }
}
void DxfRWInterface::writeTextstyles() {}
void DxfRWInterface::writeVports() {}
void DxfRWInterface::writeDimstyles() {}
void DxfRWInterface::writeAppId() {}

void DxfRWInterface::resetWriter(const std::string& fname) {
  m_dxf_read_writer = std::make_shared<dxfRW>(fname.c_str());
  m_cells.clear();
  m_layer_name.clear();
  m_post_sim_polygons.clear();
}

void DxfRWInterface::resetReader(const std::string& filename, const std::string& top_cell_name) {
  m_dxf_read_writer = std::make_shared<dxfRW>(filename.c_str());
  m_cells.clear();
  m_name_layer.clear();
  m_curr_cell.reset();
  m_layer = 256;
  m_top_cell = std::make_shared<qlib::Cell>();
  m_top_cell->name = top_cell_name;
  m_cells.insert(m_top_cell);
}
}  // namespace qlib

#ifdef __EMSCRIPTEN__
#include <emscripten/bind.h>
#include <emscripten/val.h>
using namespace emscripten;
void bind_dxfrw() {
  register_map<std::string, uint32_t>("LayerConfig");
  register_vector<std::shared_ptr<Cell>>("VectorCell");

  class_<DxfRWInterface>("DxfConvertor")
      .smart_ptr<std::shared_ptr<DxfRWInterface>>("DxfConvertor")
      .constructor(optional_override([]() { return std::make_shared<DxfRWInterface>(); }))
      .function("write_dxf", optional_override([](DxfRWInterface& self, const std::string& filename, val js_cells,
                                                  const std::map<std::string, uint32_t>& layer_config) {
                  std::vector<std::shared_ptr<Cell>> cells;
                  size_t count = js_cells["length"].as<size_t>();
                  for (size_t i = 0; i < count; i++) {
                    cells.push_back(js_cells[i].as<std::shared_ptr<Cell>>());
                  }
                  std::unordered_map<uint32_t, std::string> layer_name;
                  for (auto&& i : layer_config) {
                    layer_name.insert({i.second, i.first});
                  }
                  self.write_dxf(filename, cells, layer_name);
                }))
      .function("read_dxf", &DxfRWInterface::read_dxf);
}
#endif